#include "pch.h"
//#include "ViewfinderRenderer.h"
//
//#include "BufferWrapper.h"
//
//using namespace NiklasKarl::WarpCam::Native;
//using namespace DirectX;
//using namespace Microsoft::WRL;
//using namespace Windows::UI::Core;
//using namespace Windows::Foundation;
//using namespace Windows::Graphics::Display;
//using namespace Windows::Storage::Streams;
//
//ViewfinderRenderer::ViewfinderRenderer(IViewfinderSource^ source) :
//	m_source(source),
//	m_pDevice(nullptr),
//	m_pContext(nullptr),
//	m_pRenderTarget(nullptr),
//	m_pRenderTargetView(nullptr),
//	m_pVertexShader(nullptr),
//	m_pPixelShader(nullptr),
//	m_pInputLayout(nullptr),
//	m_pVertexBuffer(nullptr),
//	m_pBackgroundTexture(nullptr),
//	m_pBackgroundTextureView(nullptr),
//	m_loadingComplete(false)
//{
//}
//
//void ViewfinderRenderer::Initialize()
//{
//	CreateDeviceResources();
//}
//
//void ViewfinderRenderer::CreateDeviceResources()
//{
//	ID3D11Device *pDevice = nullptr;
//	ID3D11DeviceContext *pContext = nullptr;
//
//	UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
//
//#if defined(_DEBUG)
//	creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
//#endif
//
//	D3D_FEATURE_LEVEL featureLevels[] =
//	{
//		D3D_FEATURE_LEVEL_9_3
//	};
//
//	HRESULT hr = D3D11CreateDevice(
//		nullptr,
//		D3D_DRIVER_TYPE_HARDWARE,
//		nullptr,
//		creationFlags,
//		featureLevels,
//		ARRAYSIZE(featureLevels),
//		D3D11_SDK_VERSION,
//		&pDevice,
//		&m_featureLevel,
//		&pContext
//		);
//	if (SUCCEEDED(hr))
//	{
//		hr = pDevice->QueryInterface(IID_PPV_ARGS(&m_pDevice));
//	}
//	if (SUCCEEDED(hr))
//	{
//		hr = pContext->QueryInterface(IID_PPV_ARGS(&m_pContext));
//	}
//	if (SUCCEEDED(hr))
//	{
//		CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(VertexPositionCoord) * 4, D3D11_BIND_VERTEX_BUFFER);
//
//		hr = m_pDevice->CreateBuffer(
//			&vertexBufferDesc,
//			nullptr,
//			&m_pVertexBuffer
//			);
//	}
//	if (SUCCEEDED(hr))
//	{
//		auto loadVSTask = DX::ReadDataAsync("VertexShader.cso");
//		auto loadPSTask = DX::ReadDataAsync("PixelShader.cso");
//
//		auto createVSTask = loadVSTask.then([this](Platform::Array<byte>^ fileData) {
//			const D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
//			{
//				{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
//				{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
//			};
//			
//			HRESULT hr = m_pDevice->CreateVertexShader(
//				fileData->Data,
//				fileData->Length,
//				nullptr,
//				&m_pVertexShader
//				);
//			if (SUCCEEDED(hr))
//			{
//				hr = m_pDevice->CreateInputLayout(
//					vertexDesc,
//					ARRAYSIZE(vertexDesc),
//					fileData->Data,
//					fileData->Length,
//					&m_pInputLayout
//					);
//			}
//
//			DX::ThrowIfFailed(hr);
//		});
//
//		auto createPSTask = loadPSTask.then([this](Platform::Array<byte>^ fileData) {
//			D3D11_SAMPLER_DESC samplerDesc = D3D11_SAMPLER_DESC();
//			samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
//			samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
//			samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
//			samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
//			samplerDesc.MinLOD = 0.0f;
//			samplerDesc.MaxLOD = FLT_MAX;
//			samplerDesc.MipLODBias = 0.0f;
//			samplerDesc.MaxAnisotropy = 16;
//			samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
//			samplerDesc.BorderColor[0] = 0.0f;
//			samplerDesc.BorderColor[1] = 0.0f;
//			samplerDesc.BorderColor[2] = 0.0f;
//			samplerDesc.BorderColor[3] = 0.0f;
//
//			HRESULT hr = m_pDevice->CreatePixelShader(
//				fileData->Data,
//				fileData->Length,
//				nullptr,
//				&m_pPixelShader
//				);
//			if (SUCCEEDED(hr))
//			{
//				hr = m_pDevice->CreateSamplerState(&samplerDesc, &m_pBackgroundTextureSampler);
//			}
//
//			DX::ThrowIfFailed(hr);
//		});
//
//		auto createRectTask = (createPSTask && createVSTask).then([this]() {
//			m_loadingComplete = true;
//		});
//	}
//
//	SafeRelease(&pDevice);
//	SafeRelease(&pContext);
//
//	DX::ThrowIfFailed(hr);
//}
//
//void ViewfinderRenderer::CreateWindowSizeDependentResources()
//{
//	CD3D11_TEXTURE2D_DESC renderTargetDesc(
//		DXGI_FORMAT_B8G8R8A8_UNORM,
//		static_cast<UINT>(m_renderTargetSize.Width),
//		static_cast<UINT>(m_renderTargetSize.Height),
//		1U,
//		1U,
//		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
//		D3D11_USAGE_DEFAULT,
//		0U,
//		1U,
//		0U,
//		D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX | D3D11_RESOURCE_MISC_SHARED_NTHANDLE
//		);
//	
//	HRESULT hr = m_pDevice->CreateTexture2D(
//		&renderTargetDesc,
//		nullptr,
//		&m_pRenderTarget
//		);
//	if (SUCCEEDED(hr))
//	{
//		hr = m_pDevice->CreateRenderTargetView(
//			m_pRenderTarget,
//			nullptr,
//			&m_pRenderTargetView
//			);
//	}
//	if (SUCCEEDED(hr))
//	{
//		CD3D11_VIEWPORT viewport(
//			0.0f,
//			0.0f,
//			m_renderTargetSize.Width,
//			m_renderTargetSize.Height
//			);
//
//		m_pContext->RSSetViewports(1, &viewport);
//	}
//
//	DX::ThrowIfFailed(hr);
//}
//
//void ViewfinderRenderer::UpdateForNativeResolutionChange(float width, float height)
//{
//	m_renderTargetSize.Width = width;
//	m_renderTargetSize.Height = height;
//
//	ID3D11RenderTargetView* nullViews[] = { nullptr };
//	m_pContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
//	SafeRelease(&m_pRenderTarget);
//	SafeRelease(&m_pRenderTargetView);
//	m_pContext->Flush();
//	CreateWindowSizeDependentResources();
//}
//
//void ViewfinderRenderer::UpdateForRenderResolutionChange(float width, float height)
//{
//	m_backgroundTextureSize.Width = width;
//	m_backgroundTextureSize.Height = height;
//
//	SafeRelease(&m_pBackgroundTexture);
//	SafeRelease(&m_pBackgroundTextureView);
//
//	CD3D11_TEXTURE2D_DESC backgroundTextureDesc(
//		DXGI_FORMAT_B8G8R8A8_UNORM,
//		(UINT32)m_backgroundTextureSize.Width,
//		(UINT32) m_backgroundTextureSize.Height,
//		1U,
//		1U,
//		D3D11_BIND_SHADER_RESOURCE,
//		D3D11_USAGE_DYNAMIC,
//		D3D11_CPU_ACCESS_WRITE,
//		1U,
//		0U,
//		0U
//		);
//
//	HRESULT hr = m_pDevice->CreateTexture2D(
//		&backgroundTextureDesc,
//		nullptr,
//		&m_pBackgroundTexture
//		);
//	if (SUCCEEDED(hr))
//	{
//		hr = m_pDevice->CreateShaderResourceView(
//			m_pBackgroundTexture,
//			nullptr,
//			&m_pBackgroundTextureView
//			);
//	}
//
//	DX::ThrowIfFailed(hr);
//}
//
//void ViewfinderRenderer::UpdateForRenderOrientationChange(Nokia::Graphics::Imaging::Rotation rotation, Nokia::Graphics::Imaging::FlipMode flip)
//{
//	const XMFLOAT2 normalCoords[4] =
//	{
//		XMFLOAT2(0.0f, 0.0f),
//		XMFLOAT2(1.0f, 0.0f),
//		XMFLOAT2(1.0f, 1.0f),
//		XMFLOAT2(0.0f, 1.0f)
//	};
//
//	XMFLOAT2 coords[4] =
//	{
//		XMFLOAT2(0.0f, 0.0f),
//		XMFLOAT2(1.0f, 0.0f),
//		XMFLOAT2(1.0f, 1.0f),
//		XMFLOAT2(0.0f, 1.0f)
//	};
//
//	for (UINT32 i = 0; i < 4; i++)
//	{
//		coords[i] = normalCoords[(i + 4 - (UINT32)rotation) % 4];
//	}
//
//	if ((flip & Nokia::Graphics::Imaging::FlipMode::Vertical) == Nokia::Graphics::Imaging::FlipMode::Vertical)
//	{
//		_swab((char *) (coords + 0), (char *) (coords + 1), sizeof(XMFLOAT2));
//		_swab((char *) (coords + 3), (char *) (coords + 2), sizeof(XMFLOAT2));
//	}
//
//	if ((flip & Nokia::Graphics::Imaging::FlipMode::Horizontal) == Nokia::Graphics::Imaging::FlipMode::Horizontal)
//	{
//		_swab((char *) (coords + 0), (char *) (coords + 3), sizeof(XMFLOAT2));
//		_swab((char *) (coords + 1), (char *) (coords + 2), sizeof(XMFLOAT2));
//	}
//
//	const VertexPositionCoord rectVertices[] =
//	{
//		{ XMFLOAT2(-1.0f, 1.0f), coords[0] }, // TopLeft
//		{ XMFLOAT2(1.0f, 1.0f), coords[1] }, // TopRight
//		{ XMFLOAT2(-1.0f, -1.0f), coords[3] }, // BottomLeft
//		{ XMFLOAT2(1.0f, -1.0f), coords[2] } // BottomRight
//	};
//
//	m_pContext->UpdateSubresource(m_pVertexBuffer, 0, nullptr, rectVertices, 0, 0);
//
//	m_rotation = rotation;
//	m_flip = flip;
//}
//
//void ViewfinderRenderer::UpdateForWindowSizeChange(float width, float height)
//{
//	m_windowBounds.Width = width;
//	m_windowBounds.Height = height;
//}
//
//void ViewfinderRenderer::Update()
//{
//	D3D11_MAPPED_SUBRESOURCE resource = { 0 };
//
//	HRESULT hr = m_pContext->Map(m_pBackgroundTexture, 0, D3D11_MAP_WRITE_DISCARD, 0U, &resource);
//	if (SUCCEEDED(hr))
//	{
//		BufferWrapper ^wrapper = ref new BufferWrapper((BYTE *) resource.pData, (UINT32)m_backgroundTextureSize.Width * (UINT32)(m_backgroundTextureSize.Height + 1) * 4U);
//		m_source->RenderBitmap(
//			wrapper,
//			m_backgroundTextureSize,
//			m_rotation,
//			m_flip
//			);
//
//		m_pContext->Unmap(m_pBackgroundTexture, 0);
//	}
//}
//
//void ViewfinderRenderer::Render()
//{
//	const float clearColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
//	m_pContext->ClearRenderTargetView(m_pRenderTargetView, clearColor);
//
//	if (m_loadingComplete)
//	{
//		UINT32 vertexBufferStride = sizeof(VertexPositionCoord);
//		UINT32 vertexBufferOffset = 0U;
//
//		m_pContext->OMSetRenderTargets(1U, &m_pRenderTargetView, nullptr);
//
//		m_pContext->IASetInputLayout(m_pInputLayout);
//		m_pContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &vertexBufferStride, &vertexBufferOffset);
//		m_pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
//
//		m_pContext->VSSetShader(m_pVertexShader, nullptr, 0U);
//		m_pContext->PSSetShader(m_pPixelShader, nullptr, 0U);
//
//		m_pContext->PSSetShaderResources(0, 1, &m_pBackgroundTextureView);
//		m_pContext->PSSetSamplers(0, 1, &m_pBackgroundTextureSampler);
//
//		m_pContext->Draw(4U, 0U);
//	}
//}